#include "ota_version.h"
#include "cJSON.h"
#include "ota_http_curl.h"
#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
#include <unistd.h>
#include <sys/stat.h>


/**
 * 根据文件地址计算SHA1值，并将结果存储在字符串指针中
 * @param file_path 文件路径
 * @param sha1_str 存储SHA1值的字符串指针，需要预先分配足够的空间（41字节，包括结束符）
 * @return 成功返回0，失败返回-1
 */
int ota_http_curl_calculate_sha1(const char *file_path, char *sha1_str) {
    log_info("calculate sha1:%s",file_path);
    FILE *file = fopen(file_path, "rb");
    if (!file) {
        perror("Failed to open file");
        return -1;
    }

    unsigned char buffer[1024];
    SHA_CTX sha_ctx;
    SHA1_Init(&sha_ctx);

    size_t bytes_read;
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {
        SHA1_Update(&sha_ctx, buffer, bytes_read);
    }

    fclose(file);

    if (ferror(file)) {
        perror("Error reading file");
        return -1;
    }

    unsigned char hash[SHA_DIGEST_LENGTH];
    SHA1_Final(hash, &sha_ctx);

    for (int i = 0; i < SHA_DIGEST_LENGTH; ++i) {
        sprintf(sha1_str + (i * 2), "%02x", hash[i]);
    }

    sha1_str[SHA_DIGEST_LENGTH * 2] = '\0';

    return 0;
}

 

/**
 * 检查并下载更新
 * 1  访问 OTA 版本信息url , 获得 OTA 版本信息字符串
 * 2  解析 OTA 版本信息json字符串 cJSON
 * 3  提取 版本号
 * 4  和本地的版本号比较
 * 5  如果本地的版本号小于OTA版本号，下载更新
 * 6  下载更新结束后
 * 7  根据i下载的文件生成SHA1  或者MD5 SHA256     安全性SHA256>SHA1>MD5
 * 8  用e生成的sha1 和 OTA发布的sha1进行比较
 * 9  如果一致，则下载成功，否则下载失败删除下载的文件
 *
 *
 */
int ota_version_check(void)
{
    //    1  访问 OTA 版本信息url , 获得 OTA 版本信息字符串
    ResponseBody *response_body = ota_http_curl_get_resp(VERSION_INFO_URL);
    //  * 2  解析 OTA 版本信息json字符串 cJSON
    cJSON *json = cJSON_Parse(response_body->response_str);
    //  * 3  提取 版本号
    cJSON *major_json = cJSON_GetObjectItem(json, "major");
    cJSON *minor_json = cJSON_GetObjectItem(json, "minor");
    cJSON *patch_json = cJSON_GetObjectItem(json, "patch");

    int major = major_json->valueint;
    int minor = minor_json->valueint;
    int patch = patch_json->valueint;

    //  * 4  和本地的版本号比较
    if(major > VERSION_MAJOR 
    ||(major== VERSION_MAJOR && minor > VERSION_MINOR )
    || (major== VERSION_MAJOR && minor == VERSION_MINOR && patch > VERSION_PATCH))
    {
        log_info("发现新版本 ...版本号：%d.%d.%d",major,minor,patch);
        //  * 5  如果本地的版本号小于OTA版本号，下载更新
        log_info("开始下载更新");
        unlink(VERSION_FILE_NAME);
        ota_http_curl_download_file(VERSION_FILE_DOWNLOAD_URL, VERSION_FILE_NAME);
         sleep(2);
       log_info("开始下载完成，开始验证文件完整性");
        //  * 6  下载更新结束后
        //  * 7  根据i下载的文件生成SHA1  或者MD5 SHA256     安全性SHA256>SHA1>MD5
        char local_sha1[41]={0};
        ota_http_curl_calculate_sha1(VERSION_FILE_NAME,local_sha1);

         //  * 8  用e生成的sha1 和 OTA发布的sha1进行比较
         cJSON *sha1_json = cJSON_GetObjectItem(json, "sha1");
         char *ota_sha1= sha1_json->valuestring;
         log_info("获得下载n文件的 sha1 %s",local_sha1);
         log_info("获得远端公布的 sha1:%s",ota_sha1);
         cJSON_Delete(json);
         if(strcmp(ota_sha1,local_sha1)==0)
         {
             //  * 9  如果一致，则更新成功
             log_info("更新完成 重启设备");
             // 要重启
            return 0;
         }else
         {
             //  * 9  如果不一致，则更新失败
            //unlink(VERSION_FILE_NAME);
            return -1;
         }

    }else{
        cJSON_Delete(json);
    }
 
    return -1;
}

int  ota_version_check_daily(void)
{
    while(1){
        ota_version_check();
        sleep(CHECK_INTERVAL_MIN *60);
    }
    return 0;
}

int  ota_version_print()
{
    printf("当前版本版本号：%d.%d.%d\n",VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH);
}